/*
 * To change this template, choose Tools | Templates
 * and open the template in the editor.
 */

package shaman.storage.impl.util;

import java.util.Collection;
import java.util.Iterator;
import java.util.List;
import java.util.ListIterator;

/**
 *
 * @author dmitriy
 */
public class IntegerRangeList implements List<String> {

    private final long rangeLow;
    private final long rangeHigh;

    private static class IntegerRangeIterator implements ListIterator<String> {

        private final long rangeLow;
        private final long rangeHigh;
        private long current;

        public IntegerRangeIterator(long rangeLow, long rangeHigh, long current) {
            this.rangeLow = rangeLow;
            this.rangeHigh = rangeHigh;
            this.current = current-1;
            if (current<rangeLow || current>rangeHigh)
                throw new IndexOutOfBoundsException("Starting index out of bounds of list");
        }

        public void add(String e) {
            throw new UnsupportedOperationException("List not modifyable");
        }

        public boolean hasNext() {
            return (current<rangeHigh);
        }

        public boolean hasPrevious() {
            return (current>=rangeLow);
        }

        public String next() {
            if (current<rangeHigh)
                return String.valueOf(++current);
            return null;
        }

        public int nextIndex() {
            return (int) (current-rangeLow+1);
        }

        public int previousIndex() {
            return (int) (current-rangeLow);
        }

        public String previous() {
            if (current>=rangeLow)
                return String.valueOf(current--);
            return null;
        }

        public void remove() {
            throw new UnsupportedOperationException("List not modifyable");
        }

        public void set(String e) {
            throw new UnsupportedOperationException("List not modifyable");
        }

    }

    private static class NoObjectException extends Exception {

        public NoObjectException() {
        }

        public NoObjectException(String message) {
            super(message);
        }
    }

    public IntegerRangeList(long rangeLow, long rangeHigh) {
        if (rangeHigh<rangeLow)
            throw new IllegalArgumentException("The lower bound is above the higher bound");
        this.rangeLow = rangeLow;
        this.rangeHigh = rangeHigh;
    }

    public int size() {
        return (int) (rangeHigh-rangeLow+1);
    }

    public boolean isEmpty() {
        return false;
    }

    public boolean contains(Object o) {
        return indexOf(o)>-1;
    }

    public Iterator<String> iterator() {
        return new IntegerRangeIterator(rangeLow, rangeHigh, rangeLow);
    }

    public Object[] toArray() {
        int arraySize;
        arraySize=size();
        Object[] ret=new Object[arraySize];
        int i;
        for (i=0; i<arraySize; i++)
        {
            long cur=rangeLow+i;
            ret[i]=String.valueOf(cur);
        }
        return ret;
    }

    public <T> T[] toArray(T[] a) {
        int arraySize;
        arraySize=size();
        String[] ret;
        if (a.length>=arraySize)
            ret=(String[]) a;
        else
            ret=new String[arraySize];
        int i;
        for (i=0; i<arraySize; i++)
        {
            long cur=rangeLow+i;
            ret[i]=String.valueOf(cur);
        }
        return (T[]) ret;
    }

    public boolean add(String e) {
        throw new UnsupportedOperationException("List not modifyable");
    }

    public boolean remove(Object o) {
        throw new UnsupportedOperationException("List not modifyable");
    }

    public boolean containsAll(Collection<?> c) {
        for (Object o: c)
        {
            if (indexOf(o)<0)
                return false;
        }
        return true;
    }

    public boolean addAll(Collection<? extends String> c) {
        throw new UnsupportedOperationException("List not modifyable");
    }

    public boolean addAll(int index, Collection<? extends String> c) {
        throw new UnsupportedOperationException("List not modifyable");
    }

    public boolean removeAll(Collection<?> c) {
        throw new UnsupportedOperationException("List not modifyable");
    }

    public boolean retainAll(Collection<?> c) {
        throw new UnsupportedOperationException("List not modifyable");
    }

    public void clear() {
        throw new UnsupportedOperationException("List not modifyable");
    }

    public String get(int index) {
        long val=rangeLow+index;
        if (val<rangeLow || val>rangeHigh)
            return null;
        return String.valueOf(val);
    }

    public String set(int index, String element) {
        throw new UnsupportedOperationException("List not modifyable");
    }

    public void add(int index, String element) {
        throw new UnsupportedOperationException("List not modifyable");
    }

    public String remove(int index) {
        throw new UnsupportedOperationException("List not modifyable");
    }

    public int indexOf(Object o) {
        long val;
        if (o instanceof Integer)
            val=((Integer) o).longValue();
        else if (o instanceof Long)
            val=((Long) o).longValue();
        else if (o instanceof String)
        {
            try {
                val=Long.parseLong((String) o)-rangeLow;
            } catch (NumberFormatException ex) {
                val=-1;
            }
        }
        else
            val=-1;
        if (0<=val && val+rangeLow<=rangeHigh)
            return (int) val;
        else
            return -1;
    }

    public int lastIndexOf(Object o) {
        return indexOf(o);
    }

    public ListIterator<String> listIterator() {
        return new IntegerRangeIterator(rangeLow, rangeHigh, rangeLow);
    }

    public ListIterator<String> listIterator(int index) {
        return new IntegerRangeIterator(rangeLow, rangeHigh, rangeLow+index);
    }

    public List<String> subList(int fromIndex, int toIndex) {
        long low=rangeLow+fromIndex;
        if (low<rangeLow || low>rangeHigh)
            throw new IllegalArgumentException("Lower bound outside list");
        long high=rangeLow+toIndex;
        if (high<rangeLow || high>rangeHigh)
            throw new IllegalArgumentException("Upper bound outside list");
        return new IntegerRangeList(rangeLow, rangeHigh);
    }

}
